//------------------------------------------------
// alu.v
//
// James Forrest, 2013
// Based on code by:
// David_Harris@hmc.edu 3 November 2005
//
// Pipelined MIPS processor
//------------------------------------------------

module alu(input      [31:0] a, b, 
           input       [3:0] alucont, 
           output reg [31:0] result,
           output            overflow
           );

    wire [31:0] b2, sum;
	wire  [4:0] shamt;
	wire        slt;

    assign #1 b2    = alucont[2] ? ~b:b; 
    assign #1 sum   = $signed(a) + b2 + alucont[2];
	assign #1 slt   = {{31{1'b0}}, alucont[3] ? (a < b) : ($signed(a) < $signed(b))};
	assign #1 shamt = alucont[2] ? a[4:0] : a[10:6];

    assign #1 overflow = (a[31] == b2[31]) & (a[31] != sum[31]) ? 1 : 0;

    always @ (*)
        case(alucont[3:0])
            4'b0000: result <= #1 a & b;         // and
            4'b0001: result <= #1 a | b;         // or
            4'b0100: result <= #1 a ^ b;         // xor
            4'b0101: result <= #1 ~(a | b);      // nor
            4'b0010: result <= #1 sum;           // add
            4'b0110: result <= #1 sum;           // sub
            4'b0111: result <= #1 slt;           // slt
            4'b1011: result <= #1 slt;           // sltu
            4'b1000: result <= #1 b <<  shamt;   // sll
            4'b1001: result <= #1 b >>  shamt;   // srl
            4'b1010: result <= #1 b >>> shamt;   // sra
            4'b1100: result <= #1 b <<  shamt;   // sllv
            4'b1101: result <= #1 b >>  shamt;   // srlv
            4'b1110: result <= #1 b >>> shamt;   // srav
            4'b1111: result <= #1 b << 16;       // lui (I-Type)
            default: result <= #1 {32{1'bx}};    // ???
        endcase
endmodule
